﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Threading;
using ClassLibraryMessageDispacher;
using System.Collections.Concurrent;

namespace ClassLibrarySentRecvMessageSynWorkBase
{ 
    public struct messageDIC_KEY {
     public   ulong FLGID;
     public   MessagePackagePath source;
     public   MessagePackagePath dest;
    };
    class snyPushMessagepackage
    {

        public MessagePackage sendMes = null;
        public MessagePackage getMes = null;
        private Semaphore Semp = new Semaphore(0, 1);
        public  snyPushMessagepackage()
        {

        }
        /// <summary>
        /// creat papdsa
        /// </summary>
        /// <param name="Imes"></param>
        public void CreatSentMessagePackage(ref MessagePackage Imes)
        {
            sendMes = Imes;
        }
        public bool wait(int waittime)
        {

          return  Semp.WaitOne(waittime);
        }

        public void release()
        {
            Semp.Release();
        }
    }

    public class ClassMessageSynWork
    {   
        private ConcurrentDictionary<messageDIC_KEY, snyPushMessagepackage> dic = new ConcurrentDictionary<messageDIC_KEY, snyPushMessagepackage>();

        private ConcurrentQueue<MessagePackage> idc_back_recv = new ConcurrentQueue< MessagePackage>();
        private static int rev_count_key = 0;
        /// <summary>
        /// 通知消息回调
        /// </summary>
        public FunctionNotifyComStr notify_event_func = null;
        /// <summary>
        /// 对接方主推消息回调
        /// </summary>
        public FunctionUpDataPushComStr updatapush_event_func = null;
       private  Thread disthread = null;
        public void pushMessage_FunctionMessageOutCom(ref MessagePackage mes)
        {
            if (idc_back_recv.Count < 100)
            {
                idc_back_recv.Enqueue(mes);
            }else
            {
                idc_back_recv.TryDequeue(out MessagePackage out1);
                idc_back_recv.Enqueue(mes);
            }
        }

        public ClassMessageSynWork()
        {
            disthread = new Thread(back_recv_thread);
            disthread.Priority = ThreadPriority.Normal;
            disthread.IsBackground = true;
            disthread.Start();        
        }
         ~ClassMessageSynWork()
        {
            
        }
        private void back_recv_thread(object inparam)
        {
            while (true)
            {
                Thread.Sleep(2);
                for (int i = 0; i < idc_back_recv.Count; i++)
                {
                    idc_back_recv.TryDequeue(out MessagePackage mespreq_m);

                    switch (mespreq_m.proType)
                    {
                        case ProductType.returned:
                            {
                                bool ishaveSendedReback_inDic = false;
                                foreach (var obj in dic)
                                {
                                    if (mespreq_m.squence == (obj).Key.FLGID)
                                    {
                                        obj.Value.getMes = mespreq_m;
                                        obj.Value.release();
                                        ishaveSendedReback_inDic = true;
                                        dic.TryRemove(obj.Key, out snyPushMessagepackage ouum);
                                        break;
                                    }

                                }

                                if (ishaveSendedReback_inDic)
                                {
                                    break;
                                }
                                else
                                {
                                    idc_back_recv.Enqueue(mespreq_m);
                                }
                            }
                            break;

                        case ProductType.request: { break; }

                        case ProductType.updatapush:
                            {

                                if (updatapush_event_func != null) updatapush_event_func(ref mespreq_m);
                            }
                            break;

                        case ProductType.notifyevent:
                            {

                             if(notify_event_func != null) notify_event_func(ref mespreq_m.notifyStr);


                            }
                            break;

                        default:break;
                    }

                }
            }
        }
        //  public override 
        public bool Send(ref MessagePackage inMes, out MessagePackage outMes)
        {
            outMes = null;
            try
            {
                snyPushMessagepackage synSented = new snyPushMessagepackage();
                synSented.CreatSentMessagePackage(ref inMes);
                messageDIC_KEY key = new messageDIC_KEY();
                key.FLGID = inMes.squence;
                dic.TryAdd(key, synSented);
                ClassMessagerDispacher.instance.PushMessageIn(ref inMes);
                bool cmdre = false;
                if (inMes.isNeedReback == true)
                {
                    cmdre = synSented.wait(1000 * 3);
                    if (cmdre) { outMes = synSented.getMes; }
                }else
                {
                    cmdre = true;
                }
                return cmdre;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message + "\r\n");
                return false;
            }

        }
    }
}
